home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / minix / namei.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  18.7 KB  |  828 lines

  1. /*
  2.  *  linux/fs/minix/namei.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file README.legal in the main directory of this archive
  8.  * for more details.
  9.  */
  10.  
  11. #include <linux/sched.h>
  12. #include <linux/minix_fs.h>
  13. #include <linux/kernel.h>
  14. #include <linux/string.h>
  15. #include <linux/stat.h>
  16. #include <linux/fcntl.h>
  17. #include <linux/errno.h>
  18.  
  19. #include <asm/segment.h>
  20.  
  21. /*
  22.  * comment out this line if you want names > info->s_namelen chars to be
  23.  * truncated. Else they will be disallowed (ENAMETOOLONG).
  24.  */
  25. /* #define NO_TRUNCATE */
  26.  
  27. static inline int namecompare(int len, int maxlen,
  28.     const char * name, const char * buffer)
  29. {
  30.     if (len >= maxlen || !buffer[len]) {
  31.         return strncmp (name, buffer, len) == 0;
  32.     }
  33.     return 0;
  34. }
  35.  
  36. /*
  37.  * ok, we cannot use strncmp, as the name is not in our data space.
  38.  * Thus we'll have to use minix_match. No big problem. Match also makes
  39.  * some sanity tests.
  40.  *
  41.  * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure.
  42.  */
  43. static int minix_match(int len, const char * name,
  44.     struct buffer_head * bh, unsigned long * offset,
  45.     struct minix_sb_info * info)
  46. {
  47.     struct minix_dir_entry * de;
  48.  
  49.     de = (struct minix_dir_entry *) (bh->b_data + *offset);
  50.     *offset += info->s_dirsize;
  51.     if (!de->inode || (ulong)len > info->s_namelen)
  52.     return 0;
  53.     /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
  54.     if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
  55.     return 1;
  56.     return namecompare(len,info->s_namelen,name,de->name);
  57. }
  58.  
  59. /*
  60.  *    minix_find_entry()
  61.  *
  62.  * finds an entry in the specified directory with the wanted name. It
  63.  * returns the cache buffer in which the entry was found, and the entry
  64.  * itself (as a parameter - res_dir). It does NOT read the inode of the
  65.  * entry - you'll have to do that yourself if you want to.
  66.  */
  67. static struct buffer_head * minix_find_entry(struct inode * dir,
  68.     const char * name, int namelen, struct minix_dir_entry ** res_dir)
  69. {
  70.     unsigned long block, offset;
  71.     struct buffer_head * bh;
  72.     struct minix_sb_info * info;
  73.  
  74.     *res_dir = NULL;
  75.     if (!dir || !dir->i_sb)
  76.         return NULL;
  77.     info = &dir->i_sb->u.minix_sb;
  78.     if ((ulong)namelen > info->s_namelen) {
  79. #ifdef NO_TRUNCATE
  80.         return NULL;
  81. #else
  82.         namelen = info->s_namelen;
  83. #endif
  84.     }
  85.     bh = NULL;
  86.     block = offset = 0;
  87.     while (block*BLOCK_SIZE+offset < (ulong)dir->i_size) {
  88.         if (!bh) {
  89.             bh = minix_bread(dir,block,0);
  90.             if (!bh) {
  91.                 block++;
  92.                 continue;
  93.             }
  94.         }
  95.         *res_dir = (struct minix_dir_entry *) (bh->b_data + offset);
  96.         if (minix_match(namelen,name,bh,&offset,info))
  97.             return bh;
  98.         if (offset < bh->b_size)
  99.             continue;
  100.         brelse(bh);
  101.         bh = NULL;
  102.         offset = 0;
  103.         block++;
  104.     }
  105.     brelse(bh);
  106.     *res_dir = NULL;
  107.     return NULL;
  108. }
  109.  
  110. int minix_lookup(struct inode * dir,const char * name, int len,
  111.     struct inode ** result)
  112. {
  113.     int ino;
  114.     struct minix_dir_entry * de;
  115.     struct buffer_head * bh;
  116.  
  117.     *result = NULL;
  118.     if (!dir)
  119.         return -ENOENT;
  120.     if (!S_ISDIR(dir->i_mode)) {
  121.         iput(dir);
  122.         return -ENOENT;
  123.     }
  124.     if (!(bh = minix_find_entry(dir,name,len,&de))) {
  125.         iput(dir);
  126.         return -ENOENT;
  127.     }
  128.     ino = de->inode;
  129.     brelse(bh);
  130.     if (!(*result = iget(dir->i_sb,ino))) {
  131.         iput(dir);
  132.         return -EACCES;
  133.     }
  134.     iput(dir);
  135.     return 0;
  136. }
  137.  
  138. /*
  139.  *    minix_add_entry()
  140.  *
  141.  * adds a file entry to the specified directory, returning a possible
  142.  * error value if it fails.
  143.  *
  144.  * NOTE!! The inode part of 'de' is left at 0 - which means you
  145.  * may not sleep between calling this and putting something into
  146.  * the entry, as someone else might have used it while you slept.
  147.  */
  148. static int minix_add_entry(struct inode * dir,
  149.     const char * name, int namelen,
  150.     struct buffer_head ** res_buf,
  151.     struct minix_dir_entry ** res_dir)
  152. {
  153.     unsigned int i;
  154.     unsigned long block, offset;
  155.     struct buffer_head * bh;
  156.     struct minix_dir_entry * de;
  157.     struct minix_sb_info * info;
  158.  
  159.     *res_buf = NULL;
  160.     *res_dir = NULL;
  161.     if (!dir || !dir->i_sb)
  162.         return -ENOENT;
  163.     info = &dir->i_sb->u.minix_sb;
  164.     if ((ulong)namelen > info->s_namelen) {
  165. #ifdef NO_TRUNCATE
  166.         return -ENAMETOOLONG;
  167. #else
  168.         namelen = info->s_namelen;
  169. #endif
  170.     }
  171.     if (!namelen)
  172.         return -ENOENT;
  173.     bh = NULL;
  174.     block = offset = 0;
  175.     while (1) {
  176.         if (!bh) {
  177.             bh = minix_bread(dir,block,1);
  178.             if (!bh)
  179.                 return -ENOSPC;
  180.         }
  181.         de = (struct minix_dir_entry *) (bh->b_data + offset);
  182.         offset += info->s_dirsize;
  183.         if (block*bh->b_size + offset > (ulong)dir->i_size) {
  184.             de->inode = 0;
  185.             dir->i_size = block*bh->b_size + offset;
  186.             dir->i_dirt = 1;
  187.         }
  188.         if (de->inode) {
  189.             if (namecompare(namelen, info->s_namelen, name, de->name)) {
  190.                 brelse(bh);
  191.                 return -EEXIST;
  192.             }
  193.         } else {
  194.             dir->i_mtime = dir->i_ctime = CURRENT_TIME;
  195.             for (i = 0; i < info->s_namelen ; i++)
  196.                 de->name[i] = (i < namelen) ? name[i] : 0;
  197.             bh->b_dirt = 1;
  198.             *res_dir = de;
  199.             break;
  200.         }
  201.         if (offset < bh->b_size)
  202.             continue;
  203.         brelse(bh);
  204.         bh = NULL;
  205.         offset = 0;
  206.         block++;
  207.     }
  208.     *res_buf = bh;
  209.     return 0;
  210. }
  211.  
  212. int minix_create(struct inode * dir,const char * name, int len, int mode,
  213.     struct inode ** result)
  214. {
  215.     int error;
  216.     struct inode * inode;
  217.     struct buffer_head * bh;
  218.     struct minix_dir_entry * de;
  219.  
  220.     *result = NULL;
  221.     if (!dir)
  222.         return -ENOENT;
  223.     inode = minix_new_inode(dir);
  224.     if (!inode) {
  225.         iput(dir);
  226.         return -ENOSPC;
  227.     }
  228.     inode->i_op = &minix_file_inode_operations;
  229.     inode->i_mode = mode;
  230.     inode->i_dirt = 1;
  231.     error = minix_add_entry(dir,name,len, &bh ,&de);
  232.     if (error) {
  233.         inode->i_nlink--;
  234.         inode->i_dirt = 1;
  235.         iput(inode);
  236.         iput(dir);
  237.         return error;
  238.     }
  239.     de->inode = inode->i_ino;
  240.     bh->b_dirt = 1;
  241.     brelse(bh);
  242.     iput(dir);
  243.     *result = inode;
  244.     return 0;
  245. }
  246.  
  247. int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
  248. {
  249.     int error;
  250.     struct inode * inode;
  251.     struct buffer_head * bh;
  252.     struct minix_dir_entry * de;
  253.  
  254.     if (!dir)
  255.         return -ENOENT;
  256.     bh = minix_find_entry(dir,name,len,&de);
  257.     if (bh) {
  258.         brelse(bh);
  259.         iput(dir);
  260.         return -EEXIST;
  261.     }
  262.     inode = minix_new_inode(dir);
  263.     if (!inode) {
  264.         iput(dir);
  265.         return -ENOSPC;
  266.     }
  267.     inode->i_uid = current->euid;
  268.     inode->i_mode = mode;
  269.     inode->i_op = NULL;
  270.     if (S_ISREG(inode->i_mode))
  271.         inode->i_op = &minix_file_inode_operations;
  272.     else if (S_ISDIR(inode->i_mode)) {
  273.         inode->i_op = &minix_dir_inode_operations;
  274.         if (dir->i_mode & S_ISGID)
  275.             inode->i_mode |= S_ISGID;
  276.     }
  277.     else if (S_ISLNK(inode->i_mode))
  278.         inode->i_op = &minix_symlink_inode_operations;
  279.     else if (S_ISCHR(inode->i_mode))
  280.         inode->i_op = &chrdev_inode_operations;
  281.     else if (S_ISBLK(inode->i_mode))
  282.         inode->i_op = &blkdev_inode_operations;
  283.     else if (S_ISFIFO(inode->i_mode))
  284.         init_fifo(inode);
  285.     if (S_ISBLK(mode) || S_ISCHR(mode))
  286.         inode->i_rdev = rdev;
  287.     inode->i_dirt = 1;
  288.     error = minix_add_entry(dir, name, len, &bh, &de);
  289.     if (error) {
  290.         inode->i_nlink--;
  291.         inode->i_dirt = 1;
  292.         iput(inode);
  293.         iput(dir);
  294.         return error;
  295.     }
  296.     de->inode = inode->i_ino;
  297.     bh->b_dirt = 1;
  298.     brelse(bh);
  299.     iput(dir);
  300.     iput(inode);
  301.     return 0;
  302. }
  303.  
  304. int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
  305. {
  306.     int error;
  307.     struct inode * inode;
  308.     struct buffer_head * bh, *dir_block;
  309.     struct minix_dir_entry * de;
  310.     struct minix_sb_info * info;
  311.  
  312.     if (!dir || !dir->i_sb) {
  313.         iput(dir);
  314.         return -EINVAL;
  315.     }
  316.     info = &dir->i_sb->u.minix_sb;
  317.     bh = minix_find_entry(dir,name,len,&de);
  318.     if (bh) {
  319.         brelse(bh);
  320.         iput(dir);
  321.         return -EEXIST;
  322.     }
  323.     if (dir->i_nlink >= MINIX_LINK_MAX) {
  324.         iput(dir);
  325.         return -EMLINK;
  326.     }
  327.     inode = minix_new_inode(dir);
  328.     if (!inode) {
  329.         iput(dir);
  330.         return -ENOSPC;
  331.     }
  332.     inode->i_op = &minix_dir_inode_operations;
  333.     inode->i_size = 2 * info->s_dirsize;
  334.     dir_block = minix_bread(inode,0,1);
  335.     if (!dir_block) {
  336.         iput(dir);
  337.         inode->i_nlink--;
  338.         inode->i_dirt = 1;
  339.         iput(inode);
  340.         return -ENOSPC;
  341.     }
  342.     de = (struct minix_dir_entry *) dir_block->b_data;
  343.     de->inode=inode->i_ino;
  344.     strcpy(de->name,".");
  345.     de = (struct minix_dir_entry *) (dir_block->b_data + info->s_dirsize);
  346.     de->inode = dir->i_ino;
  347.     strcpy(de->name,"..");
  348.     inode->i_nlink = 2;
  349.     dir_block->b_dirt = 1;
  350.     brelse(dir_block);
  351.     inode->i_mode = S_IFDIR | (mode & 0777 & ~current->umask);
  352.     if (dir->i_mode & S_ISGID)
  353.         inode->i_mode |= S_ISGID;
  354.     inode->i_dirt = 1;
  355.     error = minix_add_entry(dir, name, len, &bh, &de);
  356.     if (error) {
  357.         iput(dir);
  358.         inode->i_nlink=0;
  359.         iput(inode);
  360.         return error;
  361.     }
  362.     de->inode = inode->i_ino;
  363.     bh->b_dirt = 1;
  364.     dir->i_nlink++;
  365.     dir->i_dirt = 1;
  366.     iput(dir);
  367.     iput(inode);
  368.     brelse(bh);
  369.     return 0;
  370. }
  371.  
  372. /*
  373.  * routine to check that the specified directory is empty (for rmdir)
  374.  */
  375. static int empty_dir(struct inode * inode)
  376. {
  377.     unsigned int block, offset;
  378.     struct buffer_head * bh = NULL;
  379.     struct minix_dir_entry * de;
  380.     struct minix_sb_info * info;
  381.  
  382.     if (!inode || !inode->i_sb)
  383.         return 1;
  384.     info = &inode->i_sb->u.minix_sb;
  385.     block = 0;
  386.     bh = NULL;
  387.     offset = 2*info->s_dirsize;
  388.     if (inode->i_size & (info->s_dirsize-1))
  389.         goto bad_dir;
  390.     if ((ulong)inode->i_size < offset)
  391.         goto bad_dir;
  392.     bh = minix_bread(inode,0,0);
  393.     if (!bh)
  394.         goto bad_dir;
  395.     de = (struct minix_dir_entry *) bh->b_data;
  396.     if (!de->inode || strcmp(de->name,"."))
  397.         goto bad_dir;
  398.     de = (struct minix_dir_entry *) (bh->b_data + info->s_dirsize);
  399.     if (!de->inode || strcmp(de->name,".."))
  400.         goto bad_dir;
  401.     while (block*BLOCK_SIZE+offset < (ulong)inode->i_size) {
  402.         if (!bh) {
  403.             bh = minix_bread(inode,block,0);
  404.             if (!bh) {
  405.                 block++;
  406.                 continue;
  407.             }
  408.         }
  409.         de = (struct minix_dir_entry *) (bh->b_data + offset);
  410.         offset += info->s_dirsize;
  411.         if (de->inode) {
  412.             brelse(bh);
  413.             return 0;
  414.         }
  415.         if (offset < bh->b_size)
  416.             continue;
  417.         brelse(bh);
  418.         bh = NULL;
  419.         offset = 0;
  420.         block++;
  421.     }
  422.     brelse(bh);
  423.     return 1;
  424. bad_dir:
  425.     brelse(bh);
  426.     printk("Bad directory on device %04x\n",inode->i_dev);
  427.     return 1;
  428. }
  429.  
  430. int minix_rmdir(struct inode * dir, const char * name, int len)
  431. {
  432.     int retval;
  433.     struct inode * inode;
  434.     struct buffer_head * bh;
  435.     struct minix_dir_entry * de;
  436.  
  437.     inode = NULL;
  438.     bh = minix_find_entry(dir,name,len,&de);
  439.     retval = -ENOENT;
  440.     if (!bh)
  441.         goto end_rmdir;
  442.     retval = -EPERM;
  443.     if (!(inode = iget(dir->i_sb, de->inode)))
  444.         goto end_rmdir;
  445.     if ((dir->i_mode & S_ISVTX) && current->euid &&
  446.        inode->i_uid != current->euid)
  447.         goto end_rmdir;
  448.     if (inode->i_dev != dir->i_dev)
  449.         goto end_rmdir;
  450.     if (inode == dir)       /* we may not delete ".", but "../dir" is ok */
  451.         goto end_rmdir;
  452.     if (!S_ISDIR(inode->i_mode)) {
  453.         retval = -ENOTDIR;
  454.         goto end_rmdir;
  455.     }
  456.     if (!empty_dir(inode)) {
  457.         retval = -ENOTEMPTY;
  458.         goto end_rmdir;
  459.     }
  460.     if (de->inode != inode->i_ino) {
  461.         retval = -ENOENT;
  462.         goto end_rmdir;
  463.     }
  464.     if (inode->i_count > 1) {
  465.         retval = -EBUSY;
  466.         goto end_rmdir;
  467.     }
  468.     if (inode->i_nlink != 2)
  469.         printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
  470.     de->inode = 0;
  471.     bh->b_dirt = 1;
  472.     inode->i_nlink=0;
  473.     inode->i_dirt=1;
  474.     dir->i_nlink--;
  475.     inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  476.     dir->i_dirt=1;
  477.     retval = 0;
  478. end_rmdir:
  479.     iput(dir);
  480.     iput(inode);
  481.     brelse(bh);
  482.     return retval;
  483. }
  484.  
  485. int minix_unlink(struct inode * dir, const char * name, int len)
  486. {
  487.     int retval;
  488.     struct inode * inode;
  489.     struct buffer_head * bh;
  490.     struct minix_dir_entry * de;
  491.  
  492. repeat:
  493.     retval = -ENOENT;
  494.     inode = NULL;
  495.     bh = minix_find_entry(dir,name,len,&de);
  496.     if (!bh)
  497.         goto end_unlink;
  498.     if (!(inode = iget(dir->i_sb, de->inode)))
  499.         goto end_unlink;
  500.     retval = -EPERM;
  501.     if (S_ISDIR(inode->i_mode))
  502.         goto end_unlink;
  503.     if (de->inode != inode->i_ino) {
  504.         iput(inode);
  505.         brelse(bh);
  506.         current->counter = 0;
  507.         schedule();
  508.         goto repeat;
  509.     }
  510.     if ((dir->i_mode & S_ISVTX) && !suser() &&
  511.         current->euid != inode->i_uid &&
  512.         current->euid != dir->i_uid)
  513.         goto end_unlink;
  514.     if (de->inode != inode->i_ino) {
  515.         retval = -ENOENT;
  516.         goto end_unlink;
  517.     }
  518.     if (!inode->i_nlink) {
  519.         printk("Deleting nonexistent file (%04x:%lu), %d\n",
  520.             inode->i_dev,inode->i_ino,inode->i_nlink);
  521.         inode->i_nlink=1;
  522.     }
  523.     de->inode = 0;
  524.     bh->b_dirt = 1;
  525.     dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  526.     dir->i_dirt = 1;
  527.     inode->i_nlink--;
  528.     inode->i_ctime = dir->i_ctime;
  529.     inode->i_dirt = 1;
  530.     retval = 0;
  531. end_unlink:
  532.     brelse(bh);
  533.     iput(inode);
  534.     iput(dir);
  535.     return retval;
  536. }
  537.  
  538. int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
  539. {
  540.     struct minix_dir_entry * de;
  541.     struct inode * inode = NULL;
  542.     struct buffer_head * bh = NULL, * name_block = NULL;
  543.     int i;
  544.     char c;
  545.  
  546.     if (!(inode = minix_new_inode(dir))) {
  547.         iput(dir);
  548.         return -ENOSPC;
  549.     }
  550.     inode->i_mode = S_IFLNK | 0777;
  551.     inode->i_op = &minix_symlink_inode_operations;
  552.     name_block = minix_bread(inode,0,1);
  553.     if (!name_block) {
  554.         iput(dir);
  555.         inode->i_nlink--;
  556.         inode->i_dirt = 1;
  557.         iput(inode);
  558.         return -ENOSPC;
  559.     }
  560.     i = 0;
  561.     while (i < 1023 && (c=*(symname++)))
  562.         name_block->b_data[i++] = c;
  563.     name_block->b_data[i] = 0;
  564.     name_block->b_dirt = 1;
  565.     brelse(name_block);
  566.     inode->i_size = i;
  567.     inode->i_dirt = 1;
  568.     bh = minix_find_entry(dir,name,len,&de);
  569.     if (bh) {
  570.         inode->i_nlink--;
  571.         inode->i_dirt = 1;
  572.         iput(inode);
  573.         brelse(bh);
  574.         iput(dir);
  575.         return -EEXIST;
  576.     }
  577.     i = minix_add_entry(dir, name, len, &bh, &de);
  578.     if (i) {
  579.         inode->i_nlink--;
  580.         inode->i_dirt = 1;
  581.         iput(inode);
  582.         iput(dir);
  583.         return i;
  584.     }
  585.     de->inode = inode->i_ino;
  586.     bh->b_dirt = 1;
  587.     brelse(bh);
  588.     iput(dir);
  589.     iput(inode);
  590.     return 0;
  591. }
  592.  
  593. int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
  594. {
  595.     int error;
  596.     struct minix_dir_entry * de;
  597.     struct buffer_head * bh;
  598.  
  599.     if (S_ISDIR(oldinode->i_mode)) {
  600.         iput(oldinode);
  601.         iput(dir);
  602.         return -EPERM;
  603.     }
  604.     if (oldinode->i_nlink >= MINIX_LINK_MAX) {
  605.         iput(oldinode);
  606.         iput(dir);
  607.         return -EMLINK;
  608.     }
  609.     bh = minix_find_entry(dir,name,len,&de);
  610.     if (bh) {
  611.         brelse(bh);
  612.         iput(dir);
  613.         iput(oldinode);
  614.         return -EEXIST;
  615.     }
  616.     error = minix_add_entry(dir, name, len, &bh, &de);
  617.     if (error) {
  618.         iput(dir);
  619.         iput(oldinode);
  620.         return error;
  621.     }
  622.     de->inode = oldinode->i_ino;
  623.     bh->b_dirt = 1;
  624.     brelse(bh);
  625.     iput(dir);
  626.     oldinode->i_nlink++;
  627.     oldinode->i_ctime = CURRENT_TIME;
  628.     oldinode->i_dirt = 1;
  629.     iput(oldinode);
  630.     return 0;
  631. }
  632.  
  633. static int subdir(struct inode * new_inode, struct inode * old_inode)
  634. {
  635.     int ino;
  636.     int result;
  637.  
  638.     new_inode->i_count++;
  639.     result = 0;
  640.     for (;;) {
  641.         if (new_inode == old_inode) {
  642.             result = 1;
  643.             break;
  644.         }
  645.         if (new_inode->i_dev != old_inode->i_dev)
  646.             break;
  647.         ino = new_inode->i_ino;
  648.         if (minix_lookup(new_inode,"..",2,&new_inode))
  649.             break;
  650.         if (new_inode->i_ino == ino)
  651.             break;
  652.     }
  653.     iput(new_inode);
  654.     return result;
  655. }
  656.  
  657. #define PARENT_INO(buffer) \
  658. (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
  659.  
  660. /*
  661.  * rename uses retrying to avoid race-conditions: at least they should be minimal.
  662.  * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
  663.  * checks fail, it tries to restart itself again. Very practical - no changes
  664.  * are done until we know everything works ok.. and then all the changes can be
  665.  * done in one fell swoop when we have claimed all the buffers needed.
  666.  *
  667.  * Anybody can rename anything with this: the permission checks are left to the
  668.  * higher-level routines.
  669.  */
  670. static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
  671.     struct inode * new_dir, const char * new_name, int new_len)
  672. {
  673.     struct inode * old_inode, * new_inode;
  674.     struct buffer_head * old_bh, * new_bh, * dir_bh;
  675.     struct minix_dir_entry * old_de, * new_de;
  676.     struct minix_sb_info * info;
  677.     int retval;
  678.  
  679.     info = &old_dir->i_sb->u.minix_sb;
  680.     goto start_up;
  681. try_again:
  682.     brelse(old_bh);
  683.     brelse(new_bh);
  684.     brelse(dir_bh);
  685.     iput(old_inode);
  686.     iput(new_inode);
  687.     current->counter = 0;
  688.     schedule();
  689. start_up:
  690.     old_inode = new_inode = NULL;
  691.     old_bh = new_bh = dir_bh = NULL;
  692.     old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
  693.     retval = -ENOENT;
  694.     if (!old_bh)
  695.         goto end_rename;
  696.     old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
  697.     if (!old_inode)
  698.         goto end_rename;
  699.     retval = -EPERM;
  700.     if ((old_dir->i_mode & S_ISVTX) &&
  701.         current->euid != old_inode->i_uid &&
  702.         current->euid != old_dir->i_uid && !suser())
  703.         goto end_rename;
  704.     new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
  705.     if (new_bh) {
  706.         new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
  707.         if (!new_inode) {
  708.             brelse(new_bh);
  709.             new_bh = NULL;
  710.         }
  711.     }
  712.     if (new_inode == old_inode) {
  713.         retval = 0;
  714.         goto end_rename;
  715.     }
  716.     if (new_inode && S_ISDIR(new_inode->i_mode)) {
  717.         retval = -EISDIR;
  718.         if (!S_ISDIR(old_inode->i_mode))
  719.             goto end_rename;
  720.         retval = -EINVAL;
  721.         if (subdir(new_dir, old_inode))
  722.             goto end_rename;
  723.         retval = -ENOTEMPTY;
  724.         if (!empty_dir(new_inode))
  725.             goto end_rename;
  726.         retval = -EBUSY;
  727.         if (new_inode->i_count > 1)
  728.             goto end_rename;
  729.     }
  730.     retval = -EPERM;
  731.     if (new_inode && (new_dir->i_mode & S_ISVTX) &&
  732.         current->euid != new_inode->i_uid &&
  733.         current->euid != new_dir->i_uid && !suser())
  734.         goto end_rename;
  735.     if (S_ISDIR(old_inode->i_mode)) {
  736.         retval = -ENOTDIR;
  737.         if (new_inode && !S_ISDIR(new_inode->i_mode))
  738.             goto end_rename;
  739.         retval = -EINVAL;
  740.         if (subdir(new_dir, old_inode))
  741.             goto end_rename;
  742.         retval = -EIO;
  743.         dir_bh = minix_bread(old_inode,0,0);
  744.         if (!dir_bh)
  745.             goto end_rename;
  746.         if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
  747.             goto end_rename;
  748.         retval = -EMLINK;
  749.         if (!new_inode && new_dir->i_nlink >= MINIX_LINK_MAX)
  750.             goto end_rename;
  751.     }
  752.     if (!new_bh) {
  753.         retval = minix_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
  754.         if (retval)
  755.             goto end_rename;
  756.     }
  757. /* sanity checking before doing the rename - avoid races */
  758.     if (new_inode && (new_de->inode != new_inode->i_ino))
  759.         goto try_again;
  760.     if (new_de->inode && !new_inode)
  761.         goto try_again;
  762.     if (old_de->inode != old_inode->i_ino)
  763.         goto try_again;
  764. /* ok, that's it */
  765.     old_de->inode = 0;
  766.     new_de->inode = old_inode->i_ino;
  767.     old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
  768.     old_dir->i_dirt = 1;
  769.     new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
  770.     new_dir->i_dirt = 1;
  771.     if (new_inode) {
  772.         new_inode->i_nlink--;
  773.         new_inode->i_ctime = CURRENT_TIME;
  774.         new_inode->i_dirt = 1;
  775.     }
  776.     old_bh->b_dirt = 1;
  777.     new_bh->b_dirt = 1;
  778.     if (dir_bh) {
  779.         PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
  780.         dir_bh->b_dirt = 1;
  781.         old_dir->i_nlink--;
  782.         old_dir->i_dirt = 1;
  783.         if (new_inode) {
  784.             new_inode->i_nlink--;
  785.             new_inode->i_dirt = 1;
  786.         } else {
  787.             new_dir->i_nlink++;
  788.             new_dir->i_dirt = 1;
  789.         }
  790.     }
  791.     retval = 0;
  792. end_rename:
  793.     brelse(dir_bh);
  794.     brelse(old_bh);
  795.     brelse(new_bh);
  796.     iput(old_inode);
  797.     iput(new_inode);
  798.     iput(old_dir);
  799.     iput(new_dir);
  800.     return retval;
  801. }
  802.  
  803. /*
  804.  * Ok, rename also locks out other renames, as they can change the parent of
  805.  * a directory, and we don't want any races. Other races are checked for by
  806.  * "do_rename()", which restarts if there are inconsistencies.
  807.  *
  808.  * Note that there is no race between different filesystems: it's only within
  809.  * the same device that races occur: many renames can happen at once, as long
  810.  * as they are on different partitions.
  811.  */
  812. int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
  813.     struct inode * new_dir, const char * new_name, int new_len)
  814. {
  815.     static struct wait_queue * wait = NULL;
  816.     static int lock = 0;
  817.     int result;
  818.  
  819.     while (lock)
  820.         sleep_on(&wait);
  821.     lock = 1;
  822.     result = do_minix_rename(old_dir, old_name, old_len,
  823.         new_dir, new_name, new_len);
  824.     lock = 0;
  825.     wake_up(&wait);
  826.     return result;
  827. }
  828.